#include "Connection.h"
#include <TcpServer.h>
#include <sys/socket.h>
#include <utility>

namespace muduo{
    // =====================================private==============================
    void TcpServer::RemoveConnectionInLoop(const PtrConnection& con){
        auto iter= _conns.find(con->Id());
        if(iter!=_conns.end()){
            _conns.erase(iter);
        }
    }
    void TcpServer::NewConnection(int newfd){
        _next_id++;
        // thread_num = (thread_num+1)%2;
        EventLoop* loop=_pool.nextEventLoop();
        PtrConnection conn(new Connection(loop,_next_id,newfd));
        conn->SetMessageCallback(_message_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetSvrCloseCallback(_server_close_callback);
        if(_inactive_release) conn->EnableInactiveRelease(_timeout);
        conn->Establish();
        consinsert(conn);
    }
    void TcpServer::consinsert(const PtrConnection& con){_conns.insert(std::make_pair(_next_id, con));}
    void TcpServer::RunAfterInLoop(const Functor& func,int delay){
        _next_id++;
        _baseloop.AddTimerTask(_next_id, delay, func);
    }

    // =====================================public==============================
    void TcpServer::SetConnectedCallback(const ConnectedCallback& conc){_connected_callback=conc;}
    void TcpServer::SetMessageCallback(const MessageCallback& mesc){_message_callback=mesc;}
    void TcpServer::SetCloseCallback(const CloseCallback& closc){_close_callback=closc;}
    void TcpServer::SetAnyEventCallback(const AnyEventCallback& anyc){_anyevent_callback=anyc;}  
    void TcpServer::SetSvrCloseCallback(const CloseCallback& closc){_server_close_callback=closc;}  
    TcpServer::TcpServer(int port):_port(port),_pool(&_baseloop),_accepter(&_baseloop,port),_next_id(0),_inactive_release(false){
        _accepter.SetAcceptCallback(std::bind(&TcpServer::NewConnection,this,std::placeholders::_1));
        _accepter.Listen();
    }
    void TcpServer::SetInactiveRelease(int timeout){
        _inactive_release=true;
        _timeout = timeout;
    }
    void TcpServer::start(){
        // 线程池创建需要在设置线程池数量之后，所以需要放在star中
        _pool.Create();
        _baseloop.start();
    }
    void TcpServer::SetPoolNum(int num){_pool.Set_thread_num(num);}
    void TcpServer::RunAfter(const Functor& func,int delay){
        _baseloop.RunLoop(bind(&TcpServer::RunAfterInLoop,this,func,delay));
    }
    void TcpServer::RemoveConnection(const PtrConnection &con){
        _baseloop.RunLoop(bind(&TcpServer::RemoveConnectionInLoop,this,con));
    }
}